home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-11-21 | 11.9 KB | 648 lines | [TEXT/KAHL] |
- /*
- ** CTelnetInterpreter.cp
- **
- ** TurboTCP support library
- ** Generic Telnet protocol interpreter
- **
- ** Copyright © 1993, FrostByte Design / Eric Scouten
- **
- */
-
-
- #include "CTelnetInterpreter.h"
-
- #include "CTCPDriver.h"
- #include "CTCPStream.h"
- #include "CTCPResolverCall.h"
-
-
- // —— initialization ——
-
- /*______________________________________________________________________
- **
- ** ITelnetInterpreter
- **
- ** Initialize the Telnet interpreter session document.
- **
- ** aSupervisor (CApplication *): the document’s supervisor
- ** printable (Boolean): TRUE if document is printable
- ** recBufferSize (long): size of the receive buffer we need
- ** theDefaultPort (b_16): default IP port number
- ** autoReceiveSize (long): number of entries in RDS for auto-receive,
- ** 0 to disable autoreceiving
- ** autoReceiveNum (short): number of auto-receive calls to issue at once
- ** must be at least 1
- **
- */
-
- void CTelnetInterpreter::ITelnetInterpreter (CApplication *aSupervisor, Boolean printable,
- long recBufferSize, b_16 theDefaultPort,
- short autoReceiveSize, short autoReceiveNum)
-
- {
- itsState = normalChar;
- CTCPSessionDoc::ITCPSessionDoc(aSupervisor, printable, recBufferSize, theDefaultPort,
- TRUE, autoReceiveSize, autoReceiveNum);
- showFileName = FALSE;
- }
-
-
- // —— data handling methods ——
-
- /*______________________________________________________________________
- **
- ** HandleDataArrived
- **
- ** Process incoming data.
- **
- ** theData (Ptr): pointer to the block of data
- ** theDataSize (b_16): size of the data block
- ** isUrgent (Boolean): TRUE if urgent data
- **
- */
-
- void CTelnetInterpreter::HandleDataArrived (Ptr theData, b_16 theDataSize, Boolean isUrgent)
-
- {
- uchar theChar;
- uchar theLine[83];
- short lineIndex;
-
-
- // parse each character separately
-
- while (theDataSize--) {
- theChar = (uchar) (*(theData++));
-
-
- // respond to current Telnet state
-
- switch (itsState) {
-
-
- // normal operation: write character
-
- case normalChar:
-
-
- // optimization: try to grab several chars at once
-
- lineIndex = 0;
- while ((theDataSize > 1) && (theChar >= ' ') && (theChar != charIAC)) {
- theDataSize++;
- theData--;
- lineIndex = 0;
- while ((theDataSize > 0) && (((uchar) *theData) >= ' ') &&
- (*theData != charIAC) && (lineIndex < 80))
- theDataSize--, theLine[lineIndex++] = (uchar) *(theData++);
- if ((theDataSize > 0) && (*theData == charCR))
- theDataSize--, theData++, theLine[lineIndex++] = charCR;
- if ((theDataSize > 0) && (*theData == charLF))
- theDataSize--, theData++, theLine[lineIndex++] = charLF;
- theLine[lineIndex] = '\0';
- if (lineIndex)
- HandleNVTLine((char *) &theLine[0]);
- if (theDataSize < 1)
- break;
- theChar = (uchar) (*(theData++));
- theDataSize--;
- }
-
- if ((lineIndex) && !(theDataSize))
- break;
-
-
- // end of loop: test for IAC
-
- if (theChar == charIAC) {
- itsState = gotIAC;
- if (showDebug)
- PrintDebugStr("[IAC");
- }
- else
- HandleNVTChar(theChar);
- break;
-
-
- // received IAC (interpret as command)
-
- case gotIAC:
- case gotIACinSB:
- ReceivedIAC(theChar);
- break;
-
-
- // handle other cases
-
- case gotSB:
- if (theChar == charIAC) {
- itsState = gotIACinSB;
- if (showDebug)
- PrintDebugStr(" IAC");
- }
- else
- ReceivedSB(theChar);
- break;
-
- case gotWILL:
- if (showDebug)
- PrintDebugCharNum(theChar, ' ', ']');
- ReceivedWill(theChar);
- itsState = normalChar;
- break;
-
- case gotWONT:
- if (showDebug)
- PrintDebugCharNum(theChar, ' ', ']');
- ReceivedWont(theChar);
- itsState = normalChar;
- break;
-
- case gotDO:
- if (showDebug)
- PrintDebugCharNum(theChar, ' ', ']');
- ReceivedDo(theChar);
- itsState = normalChar;
- break;
-
- case gotDONT:
- if (showDebug)
- PrintDebugCharNum(theChar, ' ', ']');
- ReceivedDont(theChar);
- itsState = normalChar;
- break;
- }
- }
-
- }
-
-
- /*______________________________________________________________________
- **
- ** HandleNVTChar
- **
- ** Process a character which was recieved over Telnet for the network virtual terminal.
- **
- ** theChar (char): the character which was received
- **
- */
-
- void CTelnetInterpreter::HandleNVTChar (char theChar)
-
- {
- // null method
- }
-
-
- /*______________________________________________________________________
- **
- ** HandleNVTLine
- **
- ** Process a line (or <81 chars) which was recieved over Telnet for the network virtual
- ** terminal.
- **
- ** theLine (char *): the line which was received (C string)
- **
- */
-
- void CTelnetInterpreter::HandleNVTLine (char *theLine)
-
- {
- // null method
- }
-
-
- // —— Telnet command handling ——
-
- /*______________________________________________________________________
- **
- ** ReceivedIAC
- **
- ** Respond to a Telnet [IAC command] sequence.
- **
- ** theCommand (uchar): the command code
- **
- */
-
- void CTelnetInterpreter::ReceivedIAC (uchar theCommand)
-
- {
-
- // which command is it?
-
- switch (theCommand) {
-
- case escSE:
- if (showDebug)
- PrintDebugStr(" SE]");
- sbBfr[sbBfrIndex] = '\0';
- if (itsState == gotIACinSB)
- ReceivedSE();
- itsState = normalChar;
- break;
-
- case escNOP:
- if (showDebug)
- PrintDebugStr(" NOP]");
- itsState = normalChar;
- break;
-
- case escDM:
- if (showDebug)
- PrintDebugStr(" DM]");
- ReceivedSynch();
- itsState = normalChar;
- break;
-
- case escBRK:
- if (showDebug)
- PrintDebugStr(" BRK]");
- ReceivedBRK();
- itsState = normalChar;
- break;
-
- case escIP:
- if (showDebug)
- PrintDebugStr(" IP]");
- ReceivedIP();
- itsState = normalChar;
- break;
-
- case escAO:
- if (showDebug)
- PrintDebugStr(" AO]");
- ReceivedAO();
- itsState = normalChar;
- break;
-
- case escAYT:
- if (showDebug)
- PrintDebugStr(" AYT]");
- ReceivedAYT();
- itsState = normalChar;
- break;
-
- case escEC:
- if (showDebug)
- PrintDebugStr(" EC]");
- ReceivedEC();
- itsState = normalChar;
- break;
-
- case escEL:
- if (showDebug)
- PrintDebugStr(" EL]");
- ReceivedEL();
- itsState = normalChar;
- break;
-
- case escGA:
- if (showDebug)
- PrintDebugStr(" GA]");
- ReceivedGA();
- itsState = normalChar;
- break;
-
- case escSB:
- if (showDebug)
- PrintDebugStr(" SB");
- itsState = gotSB;
- sbBfrIndex = 0;
- break;
-
- case escWILL:
- if (showDebug)
- PrintDebugStr(" WILL");
- itsState = gotWILL;
- break;
-
- case escWONT:
- if (showDebug)
- PrintDebugStr(" WONT");
- itsState = gotWONT;
- break;
-
- case escDO:
- if (showDebug)
- PrintDebugStr(" DO");
- itsState = gotDO;
- break;
-
- case escDONT:
- if (showDebug)
- PrintDebugStr(" DONT");
- itsState = gotDONT;
- break;
-
- case escIAC:
- default:
- if (itsState == gotIACinSB) {
- ReceivedSB(theCommand);
- itsState = gotIAC;
- }
- else {
- if (showDebug)
- PrintDebugCharNum(theCommand, '?', ']');
- HandleNVTChar(theCommand);
- itsState = normalChar;
- }
- }
-
- }
-
-
- /*______________________________________________________________________
- **
- ** ReceivedWill
- **
- ** Respond to a Telnet [IAC WILL option] sequence.
- **
- ** theOption (uchar): the option code
- **
- */
-
- void CTelnetInterpreter::ReceivedWill (uchar theOption)
-
- {
- uchar respondStr[4];
-
-
- // reject all options
-
- respondStr[0] = charIAC;
- respondStr[1] = escWONT;
- respondStr[2] = theOption;
- respondStr[3] = '\0';
- if (showDebug) {
- PrintDebugStr("{IAC WONT");
- PrintDebugCharNum(theOption, ' ', '}');
- }
- itsStream->SendCString((char *) &respondStr);
- }
-
-
- /*______________________________________________________________________
- **
- ** ReceivedWont
- **
- ** Respond to a Telnet [IAC WONT option] sequence.
- **
- ** theOption (uchar): the option code
- **
- */
-
- void CTelnetInterpreter::ReceivedWont (uchar theOption)
-
- {
- // null method
- }
-
-
- /*______________________________________________________________________
- **
- ** ReceivedDo
- **
- ** Respond to a Telnet [IAC DO option] sequence.
- **
- ** theOption (uChar): the option code
- **
- */
-
- void CTelnetInterpreter::ReceivedDo (uchar theOption)
-
- {
- uchar respondStr[4];
-
-
- // reject all options
-
- respondStr[0] = charIAC;
- respondStr[1] = escWONT;
- respondStr[2] = theOption;
- respondStr[3] = '\0';
- if (showDebug) {
- PrintDebugStr("{IAC WONT");
- PrintDebugCharNum(theOption, ' ', '}');
- }
- itsStream->SendCString((char *) &respondStr);
- }
-
-
- /*______________________________________________________________________
- **
- ** ReceivedDont
- **
- ** Respond to a Telnet [IAC DONT option] sequence.
- **
- ** theOption (uchar): the option code
- **
- */
-
- void CTelnetInterpreter::ReceivedDont (uchar theOption)
-
- {
- // null method
- }
-
-
- /*______________________________________________________________________
- **
- ** ReceivedBRK
- **
- ** Respond to a Telnet [IAC BRK] sequence.
- **
- */
-
- void CTelnetInterpreter::ReceivedBRK (void)
-
- {
- // null method
- }
-
-
- /*______________________________________________________________________
- **
- ** ReceivedSynch
- **
- ** Respond to a Telnet [Urgent][IAC DM] sequence.
- **
- */
-
- void CTelnetInterpreter::ReceivedSynch (void)
-
- {
- // null method
- }
-
-
- /*______________________________________________________________________
- **
- ** ReceivedIP
- **
- ** Respond to a Telnet [IAC IP] sequence.
- **
- */
-
- void CTelnetInterpreter::ReceivedIP (void)
-
- {
- // null method
- }
-
-
- /*______________________________________________________________________
- **
- ** ReceivedAO
- **
- ** Respond to a Telnet [IAC AO] sequence.
- **
- */
-
- void CTelnetInterpreter::ReceivedAO (void)
-
- {
- // null method
- }
-
-
- /*______________________________________________________________________
- **
- ** ReceivedAYT
- **
- ** Respond to a Telnet [IAC AYT] sequence.
- **
- */
-
- void CTelnetInterpreter::ReceivedAYT (void)
-
- {
- // null method
- }
-
-
- /*______________________________________________________________________
- **
- ** ReceivedEC
- **
- ** Respond to a Telnet [IAC EC] sequence.
- **
- */
-
- void CTelnetInterpreter::ReceivedEC (void)
-
- {
- // null method
- }
-
-
- /*______________________________________________________________________
- **
- ** ReceivedEL
- **
- ** Respond to a Telnet [IAC EL] sequence.
- **
- */
-
- void CTelnetInterpreter::ReceivedEL (void)
-
- {
- // null method
- }
-
-
- /*______________________________________________________________________
- **
- ** ReceivedGA
- **
- ** Respond to a Telnet [IAC GA] sequence.
- **
- */
-
- void CTelnetInterpreter::ReceivedGA (void)
-
- {
- // null method
- }
-
-
- /*______________________________________________________________________
- **
- ** ReceivedSB
- **
- ** Receive subnegotiation parameters. Buffers characters until SE is received.
- **
- ** theChar (uchar): the latest character
- **
- */
-
- void CTelnetInterpreter::ReceivedSB (uchar theChar)
-
- {
- if (showDebug)
- PrintDebugCharNum(theChar, ' ', '\0');
- sbBfr[sbBfrIndex++] = theChar;
- }
-
-
- /*______________________________________________________________________
- **
- ** ReceivedSE
- **
- ** Parse subnegotiation parameters. Called when [IAC SE] is received.
- **
- */
-
- void CTelnetInterpreter::ReceivedSE (void)
-
- {
- // null method
- }
-
-
- /*______________________________________________________________________
- **
- ** —— debugging methods ——
- **
- ** These methods were useful to me in debugging the implementation of various Telnet
- ** options. In a terminal-based method (such as MiniTelnet’s CTelnetTerminal), these
- ** should be hooked up to routines that print the relevant data to the display screen.
- **
- */
-
- /*______________________________________________________________________
- **
- ** PrintDebugStr
- **
- ** Write a string to the terminal for debugging purposes.
- **
- ** theDebugStr (char *): the string to write
- **
- */
-
- void CTelnetInterpreter::PrintDebugStr (char *theDebugStr)
-
- {
- // null method, since no terminal is defined
- }
-
-
- /*______________________________________________________________________
- **
- ** PrintDebugCharNum
- **
- ** Print a character number for debugging. Provided as a debugging routine. The number
- ** is bracketed by the two characters indicated, i.e. if you call PrintDebugCharNum('!', '[', ']'),
- ** you get [33] written to the terminal.
- **
- ** theChar (char): the character number to write
- ** leftBracket (char): prefix to character number
- ** rightBracket (char): suffix to character number
- **
- */
-
- void CTelnetInterpreter::PrintDebugCharNum (char theChar, char leftBracket, char rightBracket)
-
- {
- // null method, since no terminal is defined
- }
-